Skip to content

Get rid of per-instance resolver and chain cache#388

Merged
akolotov merged 7 commits into
mainfrom
claude/peaceful-dijkstra-c3f606
Jun 3, 2026
Merged

Get rid of per-instance resolver and chain cache#388
akolotov merged 7 commits into
mainfrom
claude/peaceful-dijkstra-c3f606

Conversation

@akolotov
Copy link
Copy Markdown
Collaborator

@akolotov akolotov commented Jun 3, 2026

Closes #381.

Motivation

  • The PRO API migration (Route remaining data tools through the single Blockscout PRO API #380) converged every data tool onto the single, key-authenticated PRO API gateway: each tool now builds <pro_api_base_url>/<chain_id> and validates chains through ensure_chain_supported. That left the legacy per-chain instance-URL resolver (get_blockscout_base_url) and its dedicated in-memory cache (the ChainCache class, the chain_cache global, and the chain_cache_ttl_seconds config field) orphaned — no production code path calls them anymore.
  • This PR removes that dead resolver, cache, and config option, and scrubs every remaining mention of the removed symbols from the spec, the user-facing configuration surfaces, and the contributor rule files, so that neither users, Docker deployments, nor future agents are left with a dead configuration knob (BLOCKSCOUT_CHAIN_CACHE_TTL_SECONDS) or a pointer back to the removed resolver.
  • This is a pure deletion/cleanup task — there is no new behavior. Risk is low because the removed code is already off the data path; the work is sequenced so the test suite stays green and collectable at every phase boundary.

This is an internal cleanup — all tool signatures and response models are unchanged, so it is transparent to consumers.

Description

  • Phase 1 — Decouple PRO config refresh from ChainCache: ensure_pro_api_config in tools/common.py no longer calls chain_cache.replace_success_entries(...); on a successful fetch it now does exactly two things — store the PRO snapshot and invalidate the chains-list cache. The two tests whose expectations depended on that sync were updated (the replace_success_entries patch and bulk assertions removed, the store_snapshot assertions kept), and the integration test that asserted the chain cache gets warmed (test_get_chains_list_warms_cache) was deleted. The chains-list-invalidation behavior remains covered by test_ensure_pro_api_config_success_invalidates_chains_list_cache, so no coverage gap is introduced.
  • Phase 2 — Remove the resolver and the chain_cache global: Deleted get_blockscout_base_url and the chain_cache = ChainCache() global from tools/common.py (dropping the now-unused ChainCache import name; ChainNotFoundError is retained for ensure_chain_supported). Removed the seven deprecated resolver unit tests in test_chain_resolution.py and the four helper-level resolver tests in test_common_helpers.py, plus their now-orphaned imports and fixture lines. In the four *_real.py integration tests that resolved base_url only to assert the per-instance URL was absent from truncation notes, both the base_url = await get_blockscout_base_url(...) line and its paired negative assertion were removed — with no per-instance URL, that assertion has no subject. The positive <pro_api_base_url>/<chain_id>/... assertions are kept.
  • Phase 3 — Remove the ChainCache class and config field: Deleted the ChainCache class from cache.py, the chain_cache_ttl_seconds field from config.py, and the eleven test_chain_cache_* tests (plus the ChainCache import) from test_cache.py. The surviving caches (ChainsListCache, ProApiConfigCache, ContractCache) and the pro_api_config_ttl_seconds field are untouched.
  • Phase 4 — Documentation, configuration, and rule cleanup: Removed the two ChainCache / instance-URL-resolution mentions from SPEC.md, the dead BLOCKSCOUT_CHAIN_CACHE_TTL_SECONDS line from .env.example, Dockerfile, and the AGENTS.md environment-variable list, the stale chain_cache_ttl_seconds field from rule 110-new-mcp-tool.mdc, and replaced get_blockscout_base_url with the surviving ensure_chain_supported as the example helper in rule 220-integration-testing-guidelines.mdc. Per rule 900, no .cursor/AGENTS.md update was needed — these are wording/example clarifications within each rule's existing applicability scope.

Testing

  • Full default unit suite: 602 passed, 85 deselected.
  • Touched integration modules (test_common_helpers.py, test_get_chains_list_real.py, test_get_transaction_info_real.py, direct_api/) via the timeout-protected runner (scripts/run_integration_tests.py): 41 passed, 0 failed, 0 skipped, 0 timed out (a PRO API key was present, so the skip-gates did not fire and every real-data test exercised the live PRO API).
  • ruff check . and ruff format --check .: both clean.
  • Definition-of-Done sweep: git grep -nE "get_blockscout_base_url|ChainCache|chain_cache|BLOCKSCOUT_CHAIN_CACHE_TTL_SECONDS" -- ':(exclude).ai/' returns zero matches across code, tests, SPEC.md, .env.example, Dockerfile, AGENTS.md, and the two .cursor/rules files.

Summary by CodeRabbit

  • Chores

    • Version bumped to 0.16.0.dev12 across package files.
  • Documentation

    • Updated configuration and integration test guidance; clarified chain selection and API caching layers in system specification.
  • Refactor

    • Simplified chain resolution architecture by removing dedicated per-chain cache layer; configuration now requires fewer environment variables.

akolotov and others added 5 commits June 2, 2026 18:41
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@akolotov akolotov self-assigned this Jun 3, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

Warning

Review limit reached

@akolotov, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 35 minutes and 37 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 66b4a0b3-0c2d-4f71-a04d-6c08576729f1

📥 Commits

Reviewing files that changed from the base of the PR and between a3ef81f and fb99c7c.

📒 Files selected for processing (1)
  • .cursor/rules/110-new-mcp-tool.mdc

Walkthrough

This PR completes the cleanup of the per-chain Blockscout URL resolution infrastructure. The ChainCache class and get_blockscout_base_url() function are removed from production code, along with their configuration field, environment variables, and comprehensive test coverage. Data access now routes exclusively through the unified PRO API base URL.

Changes

Cache and Infrastructure Cleanup

Layer / File(s) Summary
Cache class and config field deletion
blockscout_mcp_server/cache.py, blockscout_mcp_server/config.py
The ChainCache class (with its async locking and per-chain URL caching) and the ServerConfig.chain_cache_ttl_seconds field are removed, eliminating the infrastructure for per-chain URL resolution.
Tool integration refactoring
blockscout_mcp_server/tools/common.py
The ChainCache import, module-level chain_cache instance, and get_blockscout_base_url() function are removed. The PRO API config refresh no longer synchronizes the deleted cache, and request helpers now construct base URLs directly from config.pro_api_base_url and chain ID.
Environment and documentation cleanup
.env.example, Dockerfile, AGENTS.md, .cursor/rules/110-new-mcp-tool.mdc, .cursor/rules/220-integration-testing-guidelines.mdc
Environment variable BLOCKSCOUT_CHAIN_CACHE_TTL_SECONDS is removed from .env.example and Docker image defaults. Integration testing guidance and MCP tool creation rules are updated to reference ensure_chain_supported instead of the removed get_blockscout_base_url.
Specification documentation updates
SPEC.md
Chain selection workflow is clarified to describe separate caching layers for chains-list snapshot and PRO API config mapping, with no per-chain ChainCache synchronization. Async Web3 Connection Pool validation is reworded to emphasize authoritative PRO API chain configuration.
Version increment across manifests
blockscout_mcp_server/__init__.py, pyproject.toml, server.json
Package version bumped from 0.16.0.dev11 to 0.16.0.dev12.
Unit test refactoring
tests/test_cache.py, tests/tools/test_chain_resolution.py
All ChainCache-focused tests are removed. The reset_caches fixture now only resets pro_api_config_cache. All get_blockscout_base_url cache-resolution tests are removed; remaining tests cover PRO config fetching, staleness, concurrency deduplication, and security validation.
Integration test cleanup
tests/integration/chains/test_get_chains_list_real.py, tests/integration/direct_api/test_address_logs_handler_real.py, tests/integration/direct_api/test_transaction_logs_handler_real.py, tests/integration/direct_api/test_user_operation_handler_real.py, tests/integration/test_common_helpers.py, tests/integration/transaction/test_get_transaction_info_real.py
The get_blockscout_base_url import is removed across all files. Tests that exercised base-URL resolution are deleted, and assertion logic in remaining tests is updated to validate only the presence of PRO API base-URL paths in notes, removing checks for absence of legacy base URLs.

Possibly Related PRs

  • blockscout/mcp-server#384: Migrates legacy base-URL Blockscout flow in tools/common.py to PRO API gateway, which this PR directly completes by removing the now-unused ChainCache and per-instance URL resolution.
  • blockscout/mcp-server#185: Introduced ChainCache and integrated it into get_blockscout_base_url; this PR directly reverses those changes by removing both constructs.
  • blockscout/mcp-server#379: Introduced ensure_chain_supported as a unified chain validation helper; this PR removes the legacy get_blockscout_base_url path that it replaces.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Get rid of per-instance resolver and chain cache' accurately and concisely describes the main change: removal of the per-instance URL resolver and ChainCache mechanism.
Linked Issues check ✅ Passed All code changes align with #381 requirements: ChainCache and get_blockscout_base_url removed [#381], chain_cache_ttl_seconds config deleted [#381], tests for removed cache and resolver removed [#381], documentation updated [#381], version bumped [#381], and PRO config cache decoupled [#381].
Out of Scope Changes check ✅ Passed All changes are in-scope deletions/cleanup directly supporting #381: no new features added, no unrelated modifications, and all alterations target the deprecated per-instance resolver and ChainCache mechanism.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/peaceful-dijkstra-c3f606

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@akolotov akolotov marked this pull request as ready for review June 3, 2026 16:49
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.cursor/rules/110-new-mcp-tool.mdc (1)

14-24: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove the stale metadata_url example from this config snippet.

blockscout_mcp_server/config.py no longer defines metadata_url; metadata requests are built from config.pro_api_base_url in make_metadata_request(). Leaving this example here now teaches contributors an obsolete config pattern that does not match the current server architecture.

Suggested doc fix
    class ServerConfig(BaseSettings):
        # Existing endpoints (examples)
        bs_timeout: float = 120.0
        bens_url: str = "https://bens.services.blockscout.com"
        bens_timeout: float = 30.0
        chainscout_url: str = "https://chains.blockscout.com"
        chainscout_timeout: float = 15.0
-       metadata_url: str = "https://metadata.services.blockscout.com"
        metadata_timeout: float = 30.0
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.cursor/rules/110-new-mcp-tool.mdc around lines 14 - 24, Remove the stale
example config field by deleting the metadata_url and metadata_timeout entries
from the ServerConfig snippet so it no longer suggests defining metadata_url;
update any references in the example to rely on make_metadata_request()'s use of
config.pro_api_base_url instead and ensure the ServerConfig definition only
includes current fields like bs_timeout, bens_url, bens_timeout, chainscout_url,
and chainscout_timeout to match the runtime behavior.
.cursor/rules/220-integration-testing-guidelines.mdc (1)

14-46: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Make the helper-level example use retry_on_network_error.

This section now defines the canonical helper-level pattern, but the example still calls the live endpoint directly. That contradicts the retry guidance later in the same rule and will encourage flaky copy-paste tests.

Based on learnings: “Integration tests must be resilient to transient failures … Use the retry_on_network_error helper to automatically retry these conditions.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.cursor/rules/220-integration-testing-guidelines.mdc around lines 14 - 46,
Update the example test to wrap the call to make_blockscout_request with the
retry_on_network_error helper so transient network failures are retried
automatically; specifically, call retry_on_network_error(...) passing a lambda
or coroutine that invokes make_blockscout_request (and await its result) in the
test (e.g., replace the direct await make_blockscout_request(...) with awaiting
retry_on_network_error that executes make_blockscout_request), and ensure the
rest of the assertions remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In @.cursor/rules/110-new-mcp-tool.mdc:
- Around line 14-24: Remove the stale example config field by deleting the
metadata_url and metadata_timeout entries from the ServerConfig snippet so it no
longer suggests defining metadata_url; update any references in the example to
rely on make_metadata_request()'s use of config.pro_api_base_url instead and
ensure the ServerConfig definition only includes current fields like bs_timeout,
bens_url, bens_timeout, chainscout_url, and chainscout_timeout to match the
runtime behavior.

In @.cursor/rules/220-integration-testing-guidelines.mdc:
- Around line 14-46: Update the example test to wrap the call to
make_blockscout_request with the retry_on_network_error helper so transient
network failures are retried automatically; specifically, call
retry_on_network_error(...) passing a lambda or coroutine that invokes
make_blockscout_request (and await its result) in the test (e.g., replace the
direct await make_blockscout_request(...) with awaiting retry_on_network_error
that executes make_blockscout_request), and ensure the rest of the assertions
remain unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 639ab297-dd96-4905-8888-29935f75faea

📥 Commits

Reviewing files that changed from the base of the PR and between 8dba3f3 and a3ef81f.

📒 Files selected for processing (20)
  • .cursor/rules/110-new-mcp-tool.mdc
  • .cursor/rules/220-integration-testing-guidelines.mdc
  • .env.example
  • AGENTS.md
  • Dockerfile
  • SPEC.md
  • blockscout_mcp_server/__init__.py
  • blockscout_mcp_server/cache.py
  • blockscout_mcp_server/config.py
  • blockscout_mcp_server/tools/common.py
  • pyproject.toml
  • server.json
  • tests/integration/chains/test_get_chains_list_real.py
  • tests/integration/direct_api/test_address_logs_handler_real.py
  • tests/integration/direct_api/test_transaction_logs_handler_real.py
  • tests/integration/direct_api/test_user_operation_handler_real.py
  • tests/integration/test_common_helpers.py
  • tests/integration/transaction/test_get_transaction_info_real.py
  • tests/test_cache.py
  • tests/tools/test_chain_resolution.py
💤 Files with no reviewable changes (10)
  • tests/integration/direct_api/test_user_operation_handler_real.py
  • blockscout_mcp_server/config.py
  • tests/integration/transaction/test_get_transaction_info_real.py
  • tests/integration/direct_api/test_transaction_logs_handler_real.py
  • Dockerfile
  • AGENTS.md
  • .env.example
  • tests/integration/direct_api/test_address_logs_handler_real.py
  • blockscout_mcp_server/cache.py
  • tests/integration/test_common_helpers.py

akolotov and others added 2 commits June 3, 2026 16:21
metadata_url no longer exists in ServerConfig (metadata requests route
through config.pro_api_base_url via make_metadata_request). Remove it from
both the ServerConfig and Dockerfile snippets; keep metadata_timeout, which
is still a live config field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#388 only removes code that was already dead and off the data path before
this PR (ChainCache, the chain_cache global, get_blockscout_base_url, the
chain_cache_ttl_seconds config field). The server's runtime behavior is
unchanged and the cleanup is transparent to consumers, so no dev version
bump is warranted. Revert the dev12 bump back to dev11.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@akolotov akolotov merged commit aecd3bb into main Jun 3, 2026
8 checks passed
@akolotov akolotov deleted the claude/peaceful-dijkstra-c3f606 branch June 3, 2026 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove the deprecated per-instance Blockscout URL resolution and its cache

1 participant